﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SynapseGaming.LightingSystem.Rendering;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using SynapseGaming.LightingSystem.Core;

namespace Brain.SunBurn
{
    public class DepthOfFieldPostProcessor : BaseRenderTargetPostProcessor
    {
        public GaussianBlurPostProcessor GaussianBlur;

        public Effect DofEffect { get; protected set; }

        public Vector2 HalfPixel { get; protected set; }

        public DepthOfFieldBlurType BlurType;

        public float BlurAmount = 1;

        public DepthOfFieldPostProcessor()
            : base()
        {
            BlurType = DepthOfFieldBlurType.Gaussian;

            DofEffect = Engine.Instance.ContentManager.Load<Effect>("Effects/DOF/MainDOF");           
        }

        public override void ApplyPreferences(ISystemPreferences preferences)
        {
        }

        private RenderTarget2D RenderTarget1;
        private RenderTarget2D RenderTarget2;

        public float MinDepth;
        public float MaxDepth;
        public void SetMaxDepth(float distance, float farPlane)
        {
            MaxDepth = distance / farPlane;
        }

        public override void EndFrameRendering()
        {
            GraphicsDevice device = Engine.Instance.GraphicsDevice;
            device.BlendState = BlendState.Opaque;
            device.DepthStencilState = DepthStencilState.None;
            device.RasterizerState = RasterizerState.CullNone;

            Viewport viewport = Engine.Instance.GraphicsDevice.Viewport;

            HalfPixel = new Vector2(
                0.5f / (float)Engine.Instance.GraphicsDevice.PresentationParameters.BackBufferWidth,
                0.5f / (float)Engine.Instance.GraphicsDevice.PresentationParameters.BackBufferHeight);

            ////////////////////////
            // BLUR SCENE         //
            ////////////////////////
            if (RenderTarget1 == null)
            {
                RenderTarget1 = new RenderTarget2D(device,
                    viewport.Width, viewport.Height);
            }
            if (RenderTarget2 == null)
            {
                RenderTarget2 = new RenderTarget2D(device,
                    viewport.Width, viewport.Height);
            }

            if (this.BlurType == DepthOfFieldBlurType.Gaussian)
            {
                if (GaussianBlur == null)
                {
                    GaussianBlur = new GaussianBlurPostProcessor();
                }
                GaussianBlur.BlurAmount = BlurAmount;
                GaussianBlur.BlurTexture(this.ProcessorRenderTarget,
                    RenderTarget1, RenderTarget2);
            }

            
            device.SetRenderTarget(this.PreviousRenderTarget);

            RenderTarget2D depth = this.SceneState.FrameBuffers.GetBuffer(FrameBufferType.DeferredDepthAndSpecularPower, false);

            DofEffect.Parameters["DepthBuffer"].SetValue(depth);
            DofEffect.Parameters["SceneTexture"].SetValue(this.ProcessorRenderTarget);
            DofEffect.Parameters["BlurredScene"].SetValue(this.RenderTarget2);
            DofEffect.Parameters["HalfPixel"].SetValue(HalfPixel);
            DofEffect.Parameters["MinDepth"].SetValue(this.MinDepth);
            DofEffect.Parameters["MaxDepth"].SetValue(this.MaxDepth);

            DofEffect.CurrentTechnique.Passes[0].Apply();
            FullFrameQuad.Render(device, viewport.Width, viewport.Height);

            device.BlendState = BlendState.Opaque;
            device.DepthStencilState = DepthStencilState.Default;
            device.RasterizerState = RasterizerState.CullCounterClockwise;

            device.SetRenderTarget(null);


            base.EndFrameRendering();
        }
    }
}
